
package org.mushroomdb.lock;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.mushroomdb.lock.locktypes.Lock;
import org.mushroomdb.lock.locktypes.RegisterLock;

/**
 * @author Tomas
 *
 * This class holds the Threads that are currently waiting
 * for a Lock. Has the responsabilty of sleep/wake the Threads
 * in a Lock/Unlock event.
 */
public class LockConcurrencyManager {
    
    private static LockConcurrencyManager instance;
    
    /** Holds pairs Lock/List of Threads*/
    
    private HashMap locks; 
    
    public static LockConcurrencyManager getInstance(){
        if(instance==null){
            instance =  new LockConcurrencyManager();
        }
        return instance;
    }
    
    
    private LockConcurrencyManager(){
        this.locks = new HashMap();
    }


    /**
     * Add a register to the lock map
     * @param lock
     * @param thread
     * @throws InterruptedException
     */
    public void append(Lock lock, Thread thread) throws InterruptedException {
        addLock(lock, thread);
        thread.suspend();
    }


    /**
     * @param lock
     * @param thread
     */
    private synchronized void addLock(Lock lock, Thread thread) {
        Long id = new Long(lock.getId());
        if (this.locks.containsKey(id)){
               List threadList = (List) this.locks.get(id);
               threadList.add(thread);
           }
           else{
               List list = new ArrayList();
               list.add(thread);
               this.locks.put(id,list);
           }
    }


    /**
     * remove a register from the lock map, and awakes the 
     * next Thread 
     * @param registerLock
     */
    public synchronized void remove(Lock lock) {
        Long id = new Long(lock.getId());
        if(this.locks.containsKey(id)){
            List threadList = (List) this.locks.get(id);
            Thread thread = (Thread) threadList.get(0);
            threadList.remove(0);
            thread.resume();
        }
                
    }
    
    

}
